import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.SecurityErrorEvent;
import flash.events.ProgressEvent;
import flash.external.ExternalInterface;
import flash.net.URLLoader;
import flash.net.URLLoaderDataFormat;
import flash.net.URLRequest;
import flash.net.URLVariables;

class LoaderContext 
{
	public function new() {}
	public var loader:URLLoader;
	public var index:Int;
}


class UrlLoaderContext
{
	private var index:Int;
	private var loaders:Array<LoaderContext>;
	
	public function new()
	{
		this.index = 0;
		this.loaders = new Array();
	}
	
	public function init():Void
	{
		ExternalInterface.addCallback("loadData", onLoadDataRequest);
		ExternalInterface.call("UrlLoaderContext.handleInitComplete");
	}
	
	private function onLoadDataRequest(url:String, data:Dynamic, method:String):Void
	{
		var urlLoader = new URLLoader();
		urlLoader.addEventListener(Event.COMPLETE, onloadComplete);
		urlLoader.addEventListener(IOErrorEvent.IO_ERROR, onError);
		urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
		
		var vars = new URLVariables();
		for(key in Reflect.fields(data))
			 Reflect.setField(vars,key,Reflect.field(data,key));
		
		var request = new URLRequest();
		request.method = method;
		request.data = vars;
		request.url = url;
		
		this.generateLoadID(urlLoader);
		urlLoader.load(request);
	}
	
	private function onloadComplete(e:Event):Void
	{
		var loader:URLLoader = e.target;
		var index:Int = this.getLoaderIndex(loader);
	    
		ExternalInterface.call("UrlLoaderContext.handleLoadComplete", index, loader.data);
		this.clearLoader(loader);
	}
	
	private function onError(e:IOErrorEvent):Void
	{
		var loader:URLLoader = e.target;
		var index:Int = this.getLoaderIndex(loader);		
		
		ExternalInterface.call("UrlLoaderContext.handleError", index, e.text);
		this.clearLoader(loader);
	}
	
	private function onSecurityError(e:SecurityErrorEvent):Void
	{
		var loader:URLLoader = e.target;
		var index:Int = this.getLoaderIndex(loader);		
		
		ExternalInterface.call("UrlLoaderContext.handleError", index, e.text);
		this.clearLoader(loader);
	}

	private function generateLoadID(urlLoader:Dynamic):Void
	{
		this.index += 1;
		var lc = new LoaderContext();
		lc.loader = urlLoader;
		lc.index = this.index;
		this.loaders.push(lc);

		// return index of the urlLoader
		ExternalInterface.call("UrlLoaderContext.registerLoader", this.index);
	}
	
	private function getLoaderIndex(loader:URLLoader):Int
	{
		for(i in 0...this.loaders.length)
			if(this.loaders[i].loader == loader)
				return this.loaders[i].index;
		return -1;
	}

	private function clearLoader(loader:URLLoader):Void 
	{
		for(i in 0...this.loaders.length)
			if(this.loaders[i].loader == loader)
			{
				this.loaders.remove(this.loaders[i]);
				break;
			}
	}
	
	public static function main():Void
	{
    	var urlLoaderContext = new UrlLoaderContext();
    	urlLoaderContext.init();
    }

}
